package org.gpp.proj1.ui.gui.editor.selector;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Collection;
import java.util.LinkedList;
import java.util.Map;

import javax.swing.DefaultListModel;
import javax.swing.JDialog;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import org.gpp.proj1.logic.metadata.PartCategory;
import org.gpp.proj1.logic.metadata.PartEntry;
import org.gpp.proj1.ui.gui.SRGGUIView;

/**
 * Dialog that displays a part list, from which the player may
 * make a selection. If a selection is made, a set of
 * <code>PartSelectionListener</code>s will be notified
 * 
 * @author Paolo Victor, paolovictor@gmail.com
 */
public class PartSelectorDialog extends JDialog implements ListSelectionListener, ActionListener {
	
	private static final long serialVersionUID = 8733404083552627178L;

	/**
	 * Command issued when the "Equip part" button is clicked
	 */
	private static final String EQUIP_COMMAND = "equip";

	/**
	 * Command issued when the "Cancel" button is clicked
	 */	
	private static final String CANCEL_COMMAND = "cancel";
	
	/**
	 * Map with the parts that are available for selection
	 */
	private Map<PartEntry, Integer> parts;

	/**
	 * The category that this selector will display
	 */
	private PartCategory category;

	/**
	 * The currently selected part
	 */
	private PartEntry selectedPart;
	
	/**
	 * The parts that were already selected and cannot
	 * be listed for selection
	 */
	private Collection<PartEntry> exceptions;
	
	/**
	 * The parent view
	 */
	private SRGGUIView view;
	
    private javax.swing.JButton cancelButton;
    private javax.swing.JButton equipButton;
    private javax.swing.JList partsList;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JTabbedPane jTabbedPane1;
    private javax.swing.JTextArea partDescription;
    private javax.swing.JLabel partLabel;
    private javax.swing.JLabel partPictureLabel;

    /**
     * 
     * @param view
     * @param category
     * @param exceptions
     * @param original 
     */
	private PartSelectorDialog( SRGGUIView view, PartCategory category, Collection<PartEntry> exceptions, Collection<PartEntry> original ) {

		this.view = view;
		
		this.category = category;
		
		this.exceptions = new LinkedList<PartEntry>( exceptions );

		this.parts = view.getController().getAvailableParts( category );
		
		// Restoring original parts to available parts
		for( PartEntry part : original ) {

			if( parts.containsKey( part ) ) {
				parts.put( part, parts.get( part ) + 1 );
			} else {
				parts.put( part, 1 );
			}
		}
		
		this.selectedPart = null;
		
		this.initComponents();
		
		this.updatePartsList();
	}
	
    private void initComponents() {
        this.setTitle( "Part selector: " + category.name() );
        
        this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        this.setResizable(false);
        this.setModal( true );
    	
        jTabbedPane1 = new javax.swing.JTabbedPane();
        jScrollPane1 = new javax.swing.JScrollPane();
        partsList = new javax.swing.JList();
        partLabel = new javax.swing.JLabel();
        partPictureLabel = new javax.swing.JLabel();
        jScrollPane2 = new javax.swing.JScrollPane();
        partDescription = new javax.swing.JTextArea();
        cancelButton = new javax.swing.JButton();
        equipButton = new javax.swing.JButton();
        
        jScrollPane1.setViewportView(partsList);

        jTabbedPane1.addTab(category.name(), jScrollPane1);

        partLabel.setFont(new java.awt.Font("Dialog", 1, 14));
        partLabel.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        partLabel.setText("");

        partPictureLabel.setBackground(new java.awt.Color(255, 255, 255));
        partPictureLabel.setText("");
        partPictureLabel.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        partPictureLabel.setOpaque(true);

        partDescription.setColumns(20);
        partDescription.setEditable(false);
        partDescription.setRows(5);
        partDescription.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        jScrollPane2.setViewportView(partDescription);

        cancelButton.setText("Cancel");
        cancelButton.setActionCommand( CANCEL_COMMAND );
        cancelButton.addActionListener( this );

        equipButton.setText("Equip part");
        equipButton.setActionCommand( EQUIP_COMMAND );
        equipButton.addActionListener( this );
        
        this.partsList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
        this.partsList.addListSelectionListener( this );

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(layout.createSequentialGroup()
                        .add(jTabbedPane1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 226, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                            .add(org.jdesktop.layout.GroupLayout.LEADING, partLabel, 0, 0, Short.MAX_VALUE)
                            .add(partPictureLabel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 340, Short.MAX_VALUE)
                            .add(jScrollPane2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 340, Short.MAX_VALUE)))
                    .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
                        .add(equipButton)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(cancelButton)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(layout.createSequentialGroup()
                        .add(partLabel)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(partPictureLabel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 124, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jScrollPane2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 276, Short.MAX_VALUE))
                    .add(org.jdesktop.layout.GroupLayout.TRAILING, jTabbedPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 429, Short.MAX_VALUE))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(cancelButton)
                    .add(equipButton))
                .addContainerGap())
        );
        pack();
        
		this.setLocationRelativeTo( null );
    }                        
    
    /**
     * Fills the JList with the available parts
     */
    private void updatePartsList() {
		DefaultListModel listModel = new DefaultListModel();
		
		for( PartEntry partEntry : parts.keySet() ) {
			int numCopies = parts.get( partEntry );
			
			// For each part, add its N copies
			for( int k = 0; k < numCopies; k++ ) {
				// If it's already selected, ignore
				if( exceptions.contains( partEntry ) ) {
					exceptions.remove( partEntry );
					continue;
				}
				
				listModel.addElement( partEntry.getName() );
			}
		}
		
		partsList.setModel( listModel );
		partsList.clearSelection();
	}

	/* (non-Javadoc)
	 * @see javax.swing.event.ListSelectionListener#valueChanged(javax.swing.event.ListSelectionEvent)
	 */
	public void valueChanged(ListSelectionEvent e) {
		if( e.getFirstIndex() >= 0 ) {
			String partName = (String) partsList.getModel().getElementAt( e.getFirstIndex() );
			PartEntry entry = view.getController().getPartsList().get( category ).get( partName );			
		
			// Updates label and description
			partLabel.setText( entry.getName() );
			partDescription.setText( entry.getPartDescription() );
			
			// Updates selected part
			this.selectedPart = entry;
		}
	}

	/* (non-Javadoc)
	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
	 */
	public void actionPerformed(ActionEvent e) {
		
		if( e.getActionCommand().equals( CANCEL_COMMAND ) ) {
			this.selectedPart = null;			
		}
			
		this.dispose();
	}

	/**
	 * Displays the selection dialog, returning a String with the name of the selected part
	 *
	 * @param parentView
	 * @param partSelection
	 * @param name
	 * @param name2 
	 * @param discardSelected 
	 * @return
	 */
	public static PartEntry showDialog( SRGGUIView parentView, PartCategory partSelection, Collection<PartEntry> exceptions, Collection<PartEntry> original ) {
		
		PartSelectorDialog dialog = new PartSelectorDialog( parentView, partSelection, exceptions, original );
		dialog.setVisible( true );
				
		return dialog.selectedPart;
	}
}
